home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / bsrc_p1.arc / F_RECV.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-30  |  23.3 KB  |  716 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*               The Opus Computer-Based Conversation System                */
  3. /*       (c) Copyright 1986, Wynn Wagner III, All Rights Reserved           */
  4. /*                                                                          */
  5. /*         The original Sealink protocol is copyrighted by SEA, inc.        */
  6. /*                                                                          */
  7. /*                 This module was written by W.Wagner III                  */
  8. /*        with modifications done by Bob Hartman and Rick Huebner           */
  9. /*                                                                          */
  10. /*                                                                          */
  11. /*                                                                          */
  12. /*         GENERAL PURPOSE FILE RECEPTION (Xmodem/YModem/Sealink)           */
  13. /*                                                                          */
  14. /*                                                                          */
  15. /*  This module is similar to a routine used by Opus-Cbcs (1.00).  It is    */
  16. /*  provided for your information only.  You will find routines that need   */
  17. /*  to be coded and identifiers to be resolved.                             */
  18. /*                                                                          */
  19. /*  There is absolutely no guarantee that anything here will work.  If you  */
  20. /*  break this routine, you own both pieces.                                */
  21. /*                                                                          */
  22. /*  USAGE:  You may use this material in any program with no obligation     */
  23. /*          as long as there is no charge for your program.  For more       */
  24. /*          information about commercial use, contact the "OPUSinfo HERE"   */
  25. /*          BBS (124/111).                                                  */
  26. /*                                                                          */
  27. /*                                                                          */
  28. /*--------------------------------------------------------------------------*/
  29. #include <sys/types.h>
  30. #include <sys/utime.h>
  31. #include <ctype.h>
  32. #include <stdio.h>
  33. #include "xfer.h"
  34. #include "com.h"
  35.  
  36.  
  37.  
  38.  
  39.  
  40. static   void pascal SendACK(void);
  41. static   void pascal SendNAK(void);
  42. static   void pascal getblock(void);
  43.  
  44.  
  45. /*--------------------------------------------------------------------------*/
  46. /* EXTERNALS                                                                */
  47. /*--------------------------------------------------------------------------*/
  48. extern char *UNLINK_msg;
  49. extern byte *local_CEOL;
  50. extern int remote_net, remote_node;
  51. extern int overwrite;
  52. extern int un_attended;
  53. extern int fullscreen;
  54. extern long timezone;
  55. extern int no_overdrive;
  56.  
  57. char *ultoa();
  58.  
  59.  
  60. /*--------------------------------------------------------------------------*/
  61. /* LOCALS                                                                   */
  62. /*--------------------------------------------------------------------------*/
  63. static unsigned int       block_number;
  64. static unsigned int       base_block;
  65. static char              *stat_msg;
  66. static int                sliding;
  67. static int                block_size;
  68. static int                do_chksum;
  69. static int                errs;
  70. static int                fsize1;
  71. static int                fsize2;
  72. static char              *buffer;
  73.        char              *malloc();
  74. static FILE              *infile;
  75. static char              *_fpath;
  76. static struct zero_block *header;
  77. static char               final_name[80];
  78. static int                first_block;     /* 1 = first block/Matrix bundle */
  79.  
  80. static char              *receiving       = "Receiving  ";
  81. static int   may_be_seadog;
  82. static int   netmail;
  83. static int   recv_ackless;
  84. static int   did_nak;
  85. static long  filesecs;
  86.  
  87. #define two_s "%s%s"
  88.  
  89.  
  90.  
  91. /*--------------------------------------------------------------------------*/
  92. /* SEND ACK                                                                 */
  93. /*--------------------------------------------------------------------------*/
  94. static void pascal SendACK()
  95.    begin
  96.  
  97.       if ((!recv_ackless) || (block_number == 0))
  98.          {
  99.          SENDBYTE( ACK );
  100.          if (sliding)
  101.             begin
  102.                SENDBYTE(  block_number );
  103.                SENDBYTE( ~block_number );
  104.             end
  105.          }
  106.  
  107.       if (block_number <= fsize1)
  108.          begin
  109.  
  110.             /* Non-nonsense status line.  Don't waste time will frills... */
  111.             gotoxy(locate_x,locate_y);
  112.             cputs( ultoa(((unsigned long )(block_number)),e_input,10) );
  113.  
  114.          end
  115.  
  116.       errs = 0;
  117.  
  118.    end /* SendACK */
  119.  
  120.  
  121.  
  122. /*--------------------------------------------------------------------------*/
  123. /* SEND NAK                                                                 */
  124. /*--------------------------------------------------------------------------*/
  125. static void pascal SendNAK()
  126.    begin
  127.       int   i;
  128.  
  129.       errs++;
  130.       if (errs>6)
  131.          begin
  132.             stat_msg = FUBAR_msg;
  133.             return;
  134.          end
  135.  
  136.       if (++did_nak > 8)
  137.          {
  138.          recv_ackless = 0;
  139.          }
  140.  
  141.  
  142.       CLEAR_INBOUND();
  143.  
  144.  
  145.       /*--------------------------------------------------------------------*/
  146.       /* Let the connection cool its heels.                                 */
  147.       /*--------------------------------------------------------------------*/
  148.       if (!recv_ackless)
  149.          {
  150.          if ((base_block!=block_number) or (errs>1))
  151.             do
  152.                begin
  153.                   i = TIMED_READ(1);
  154.                   if (!CARRIER)               return;
  155.                end
  156.             while(i>=0);
  157.          }
  158.  
  159.  
  160.  
  161.       if (block_number>base_block) SENDBYTE(NAK);
  162.       else
  163.          begin
  164.             if ((errs<5) and (!do_chksum)) SENDBYTE('C');
  165.             else
  166.                begin
  167.                   do_chksum = 1;
  168.                   SENDBYTE(NAK);
  169.                end
  170.          end
  171.  
  172.       if (sliding)
  173.          begin
  174.             SENDBYTE(  block_number );
  175.             SENDBYTE( ~block_number );
  176.          end
  177.  
  178.       if (block_number <= fsize1)
  179.          begin
  180.  
  181.             /* No time for anything but the bare essentials... */
  182.             gotoxy(locate_x,locate_y);
  183.             cputs( ultoa(((unsigned long )(block_number)),e_input,10) );
  184.  
  185.          end
  186.  
  187.    end /* SendNAK */
  188.  
  189.  
  190.  
  191. /*--------------------------------------------------------------------------*/
  192. /* GET BLOCK                                                                */
  193. /*--------------------------------------------------------------------------*/
  194. static void pascal getblock()
  195.    begin
  196.       register int   i;
  197.       register char *sptr;
  198.  
  199.       unsigned int   crc;
  200.       int            loop;
  201.       int            in_char;
  202.       int            is_resend;
  203.       int            blockerr;
  204.       unsigned char  chksum;
  205.  
  206.       blockerr = loop = is_resend = 0;
  207.       chksum = '\0';
  208.  
  209.  
  210.       /*--------------------------------------------------------------------*/
  211.       /* HEADER: Block number                                               */
  212.       /*--------------------------------------------------------------------*/
  213.       in_char = TIMED_READ(5);
  214.       if ( in_char != (block_number & 0xff) )
  215.          begin
  216.             if (in_char < block_number )  is_resend = 1;
  217.             else if ((block_number) or (in_char != 1))
  218.                begin
  219.                   blockerr++;
  220.                   stat_msg = SYNC_msg;
  221.                end
  222.                 else block_number = 1;
  223.          end
  224.  
  225.       /*--------------------------------------------------------------------*/
  226.       /* HEADER: Complement of the block number                             */
  227.       /*--------------------------------------------------------------------*/
  228.       i = TIMED_READ(5);
  229.       if ( (i&0xff) != ((~in_char)&0xff) )
  230.          begin
  231.             blockerr++;
  232.             stat_msg = CMPL_msg;
  233.          end
  234.  
  235.       /*--------------------------------------------------------------------*/
  236.       /* DATA                                                               */
  237.       /*--------------------------------------------------------------------*/
  238.       for (sptr=buffer, i=0; i<block_size; i++, sptr++ )
  239.          begin
  240.             if (!CARRIER)  return;
  241.  
  242.             in_char = TIMED_READ(5);
  243.             if (in_char<0)
  244.                begin
  245.                   SendNAK();
  246.                   stat_msg = TIME_msg;
  247.                   return;
  248.                end
  249.             sptr[0] = (char )in_char;
  250.          end
  251.  
  252.       /*--------------------------------------------------------------------*/
  253.       /* CHECK                                                              */
  254.       /*--------------------------------------------------------------------*/
  255.       if (do_chksum)
  256.          begin
  257.  
  258.             for(sptr=buffer,i=0; i<block_size; i++,sptr++ )
  259.                chksum += sptr[0];
  260.  
  261.             if (TIMED_READ(5)!=chksum)
  262.                begin
  263.                   stat_msg = CHK_msg;
  264.                   blockerr++;
  265.                end
  266.          end
  267.       else
  268.          begin
  269.             unsigned int lsb, msb;
  270.  
  271.             for(sptr=buffer,i=crc=0; i<block_size; i++,sptr++)
  272.                crc = xcrc(crc,(byte )sptr[0]);
  273.  
  274.  
  275.             msb    = TIMED_READ(3);
  276.             lsb    = TIMED_READ(3);
  277.             if ((lsb<0)||(msb<0))
  278.                begin
  279.                   stat_msg = SHRT_msg;
  280.                   if (!block_number) sliding = 0;
  281.                   blockerr++;
  282.                end
  283.             else if ( ((msb<<8)|lsb) != crc )
  284.                begin
  285.                   stat_msg = CRC_msg;
  286.                   blockerr++;
  287.                end
  288.          end
  289.  
  290.       if (blockerr) SendNAK();
  291.       else
  292.          begin
  293.             SendACK();
  294.             if (is_resend)    return;
  295.  
  296.             if (block_number)
  297.                begin
  298.                   if (block_number < fsize1)
  299.                      fwrite( buffer, block_size, 1, infile );
  300.                   else if (block_number == fsize1)
  301.                      fwrite ( buffer, fsize2, 1, infile);
  302.  
  303.                   if (first_block)
  304.                      begin
  305.                         struct _pkthdr *bundle;
  306.  
  307.                         bundle      = (struct _pkthdr *)buffer;
  308.                         remote_net  = bundle->orig_net;
  309.                         remote_node = bundle->orig_node;
  310.                         first_block = 0;
  311.                      end
  312.                end
  313.             else
  314.                begin
  315.                         if (!first_block)
  316.                             begin
  317.                         sptr  = &(header->name[0]);
  318.                         if (netmail)
  319.                            invent_pkt_name(sptr);
  320.  
  321.                           for(i=0; ((sptr[i])&&(i<17)); i++)
  322.                              if (sptr[i]<=' ') sptr[i]='\0';
  323.  
  324.                           if (sptr[0])
  325.                              begin
  326.                                 sprintf( final_name, two_s, _fpath, sptr );
  327.                               sptr  = final_name;
  328.                               fancy_str( sptr );
  329.  
  330.                               i  = strlen(final_name)-1;
  331.  
  332.                               if (un_attended && fullscreen)
  333.                                  {
  334.                                  clear_filetransfer();
  335.                                  gotoxy (0,13);
  336.                                  }
  337.                               else if (locate_y>1)
  338.                                  {
  339.                                  gotoxy (0, locate_y - 1);
  340.                                  }
  341.                                 cputs( sptr );
  342.                              end
  343.                           else status_line("!Grunged hdr");
  344.                             end
  345.                   else message(NULL);
  346.  
  347.                   if (header->size)
  348.                      begin
  349.                         fsize1 = (int) (header->size/128L);
  350.                         if (fsize2 = (header->size % 128)) ++fsize1;
  351.                         else                               fsize2 = 128;
  352.                         cprintf("%s %d blks", (netmail)?"     ":"", fsize1);
  353.                      end
  354.  
  355.                   if (header->time)
  356.                      begin
  357.                         filesecs = header->time;
  358.                      end
  359.                   else
  360.                      begin
  361.                         filesecs = -1;
  362.                      end
  363.  
  364.                   if (header->moi[0]) cprintf(" from %s", header->moi );
  365.  
  366.                   if (header->noacks && !no_overdrive)
  367.                      {
  368.                      recv_ackless = 1;
  369.                      }
  370.  
  371.                   if (!netmail)
  372.                      {
  373.                      if (un_attended && fullscreen)
  374.                         gotoxy (0, 13);
  375.                      set_xy(receiving);
  376.                      }
  377.  
  378.                end
  379.             block_number++;
  380.          end
  381.  
  382.    end  /* getblock */
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389. /*--------------------------------------------------------------------------*/
  390. /* GENERAL PURPOSE FILE RECEIPTION ROUTINE                                  */
  391. /*--------------------------------------------------------------------------*/
  392. char *receive_file( fpath, fname, protocol )
  393.    char *fpath, *fname, protocol;
  394.    begin
  395.       char  tmpname[80];
  396.       int   in_char;
  397.         int    block_timer;
  398.       struct utimbuf times;
  399.       long  t1, timerset();
  400.  
  401.       did_nak = 0;
  402.       filesecs = -1;
  403.       brk_disable();
  404.       XON_DISABLE();
  405.  
  406.       if (protocol == 'F')
  407.          {
  408.          may_be_seadog = 1;
  409.          netmail = 0;
  410.          protocol = 'S';
  411.          first_block = 0;
  412.          }
  413.       else if (protocol == 'B')
  414.          {
  415.          protocol = 'S';
  416.          may_be_seadog = 1;
  417.          netmail = 1;
  418.          first_block = 1;
  419.          }
  420.       else
  421.          {
  422.          may_be_seadog = 0;
  423.          netmail = 0;
  424.          first_block = 0;
  425.          }
  426.  
  427.       CLEAR_IOERR();
  428.       fsize1 = 32767;
  429.         if (fname)
  430.           for(in_char=0;fname[in_char];in_char++)
  431.              if ( (fname[in_char]=='*') || (fname[in_char]=='?') ) fname[0]='\0';
  432.  
  433.       _fpath      = fpath;
  434.       sliding     = 1;
  435.       base_block  =
  436.       do_chksum   =
  437.       errs        = 0;
  438.       block_size  = 128;
  439.  
  440.       locate_y    = wherey();
  441.       locate_x    = 3 + wherex();
  442.  
  443.       switch(protocol)
  444.          begin
  445.             case 'X' :  base_block=1; sliding=0;                        break;
  446.             case 'Y' :  base_block=1; sliding=0; block_size=1024;       break;
  447.             case 'S' :                                                  break;
  448.             case 'T' :                                                  break;
  449.             case 'M' :  base_block=1; sliding=0;                        break;
  450.             default  :  cprintf("Protocol??\r\n");                return NULL;
  451.          end
  452.  
  453.       block_number   = base_block;
  454.  
  455.       sprintf( tmpname,    "%s_TMP_.$$$", fpath  );
  456.       sprintf( final_name,  two_s, _fpath,(fname&&fname[0])?fname:"UNKNOWN.$$$");
  457.  
  458.       infile = fopen( tmpname, write_binary );
  459.       if (got_error(CREATE_msg,tmpname)) return(NULL);
  460.  
  461.       buffer   = malloc(1032);
  462.       header   = (struct zero_block *) buffer;
  463.       if (!buffer)
  464.          begin
  465.             status_line("!MEM:ulbuf");
  466.             return(NULL);
  467.          end
  468.  
  469.       if (un_attended && fullscreen)
  470.          {
  471.          gotoxy (0,13);
  472.          }
  473.       set_xy(receiving);
  474.       stat_msg  = NULL;
  475.       throughput(0,0L);
  476.  
  477.       /* If we did the SEAdog kludge, then don't send another NAK */
  478.       if (!may_be_seadog)
  479.          SendNAK();
  480.  
  481.       t1 = timerset(300);
  482.       do
  483.          begin
  484.  
  485.                 /* Pretty loose timer for things like satellite delays, etc. */
  486. /* block_timer = timerset(10);
  487. */
  488.  
  489. loop_top:
  490.             if (((KEYPRESS()) and (READKB()==27)))
  491.                begin
  492.                   stat_msg = KBD_msg;
  493.                   goto fubar;
  494.                end
  495.  
  496.             in_char  = TIMED_READ(4);
  497.  
  498.             switch( in_char )
  499.                begin
  500.                   case SOH :  /*--------------------------------------------*/
  501.                               /* SOH: 128 byte block header                 */
  502.                               /*--------------------------------------------*/
  503.                               block_size=128;
  504.                               getblock();
  505.                               t1 = timerset(300);
  506.                               break;
  507.  
  508.                   case STX :  /*--------------------------------------------*/
  509.                               /* STX: YModem 1k block header                */
  510.                               /*--------------------------------------------*/
  511.                               block_size=1024;
  512.                               getblock();
  513.                               t1 = timerset(300);
  514.                               break;
  515.  
  516.                   case SYN :  /*--------------------------------------------*/
  517.                               /* SYN: TeLink Zero block header              */
  518.                               /*--------------------------------------------*/
  519.                               do_chksum =  1;
  520.                               getblock();
  521.                               do_chksum =  0;
  522.                               t1 = timerset(300);
  523.                               break;
  524.  
  525.                   case CAN :  /*--------------------------------------------*/
  526.                               /* CAN                                        */
  527.                               /*--------------------------------------------*/
  528.                               if (TIMED_READ(2)==CAN)
  529.                                  begin
  530.                                     stat_msg = CAN_msg;
  531.                                     goto fubar;
  532.                                  end
  533.                               t1 = timerset(300);
  534.                               break;
  535.  
  536.                   case EOT :  /*--------------------------------------------*/
  537.                               /* EOT                                        */
  538.                               /*--------------------------------------------*/
  539.                               stat_msg = EOT_msg;
  540.                               t1 = timerset (20);
  541.                               while (!timeup (t1))
  542.                                  {
  543.                                  TIMED_READ(0);
  544.                                  time_release();
  545.                                  }
  546.                               if (block_number) goto done;
  547.                               else goto fubar;
  548.  
  549.                   default  :  /*--------------------------------------------*/
  550.                               /* Default                                    */
  551.                               /*--------------------------------------------*/
  552.                               if (in_char>0)
  553.                                  begin
  554.                                     if (!may_be_seadog)
  555.                                        {
  556.                                        gotoxy(locate_x,locate_y);
  557.                                        cprintf("??? [%Xh, blk %d] ",in_char,block_number);
  558.                                        set_xy(receiving);
  559.                                        }
  560.                                  end
  561.  
  562.                               /*--------------------------------------------*/
  563.                                         /* Debris is tolerable for up to the amount   */
  564.                                         /* of time we are willing to wait for a start */
  565.                                         /* of a block.  Right now it is 10 seconds.   */
  566.                               /*--------------------------------------------*/
  567. /*                                        if ( (!timeup(block_timer)) and (CARRIER) )
  568.                                             goto loop_top;
  569.                                         else
  570. */
  571.  
  572.                               /* If may_be_seadog is set, then we know we should
  573.                                  get an SOH pretty soon */
  574.                               if (timeup(t1) || !may_be_seadog)
  575.                                   SendNAK();
  576.                               break;
  577.  
  578.                end /* switch */
  579.  
  580.             if (errs>14)
  581.                begin
  582.                   stat_msg = FUBAR_msg;
  583.                   goto fubar;
  584.                end
  585.  
  586.             else if (got_error(WRITE_msg,fname))
  587.                begin
  588.                   stat_msg = IO_msg;
  589.                   goto fubar;
  590.                end
  591.  
  592.             if (stat_msg)
  593.                begin
  594.                   cputs( stat_msg );
  595.                   cputs( local_CEOL );
  596.                   stat_msg = NULL;
  597.                end
  598.  
  599.          end
  600.       while(CARRIER);
  601.  
  602.       stat_msg = CARRIER_msg;
  603.  
  604.  
  605. fubar:
  606.  
  607.       if (buffer) free(buffer);
  608.       if (infile)
  609.          begin
  610.             fclose(infile);
  611.             got_error(CLOSE_msg,tmpname);
  612.             unlink(tmpname);
  613.             got_error(UNLINK_msg,tmpname);
  614.          end
  615.  
  616.       CLEAR_OUTBOUND();
  617.  
  618.       if (stat_msg != EOT_msg)
  619.             begin
  620.             for(in_char=0; in_char<5; in_char++)
  621.                    SENDBYTE(CAN);
  622.  
  623.             status_line("!File not received: %s",stat_msg);
  624.             end;
  625.  
  626.       CLEAR_INBOUND();
  627.       return NULL;
  628.  
  629.  
  630. done:
  631.  
  632.       recv_ackless = 0;
  633.       SendACK();
  634.  
  635.       if (buffer) free(buffer);
  636.  
  637.       if (infile)
  638.          begin
  639.             int             i, j, k;
  640.             struct FILEINFO dta;
  641.  
  642.             fclose(infile);
  643.             got_error(CLOSE_msg,tmpname);
  644.  
  645.             i = strlen(tmpname)    -1;
  646.             j = strlen(final_name) -1;
  647.  
  648.             if (tmpname[i]=='.')    tmpname[i]='\0';
  649.             if (final_name[j]=='.')
  650.                {
  651.                final_name[j]='\0';
  652.                --j;
  653.                }
  654.  
  655.             i = 0;
  656.             k = is_arcmail (final_name, j);
  657.             if ((!overwrite) || k)
  658.                {
  659.                while(rename(tmpname,final_name))
  660.                   begin
  661.                      if (isdigit(final_name[j])) final_name[j]++;
  662.                      else final_name[j]='0';
  663.                      if (!isdigit(final_name[j])) return(tmpname);
  664.                      i = 1;
  665.                   end
  666.                CLEAR_IOERR();
  667.                }
  668.             else
  669.                {
  670.                unlink (final_name);
  671.                rename (tmpname, final_name);
  672.                }
  673.             if (i)
  674.                {
  675.                if (locate_y) gotoxy (0, locate_y-1);
  676.                status_line("+Dupe file renamed: %s",final_name);
  677.                }
  678.  
  679.             if (filesecs != -1)
  680.                {
  681.                tzset();
  682.                times.modtime = filesecs+timezone;
  683.                times.actime = filesecs+timezone;
  684.                utime (final_name, ×);
  685.                }
  686.  
  687.             if (!dfind(&dta,final_name,0))
  688.                begin
  689.                   if (!i)
  690.                      {
  691.                      if (locate_y) gotoxy(0,locate_y-1);
  692.                      }
  693.                   status_line("+Received-S %s",final_name);
  694.                   throughput(1,dta.size);
  695.  
  696.                   dta.size /= 1024L;
  697. #ifndef BINKLEY
  698.                   cur_user.upld += 1 + (unsigned int )dta.size;
  699.  
  700.                   if (cur_user.dnldl>0)
  701.                      cur_user.dnldl-= 1 + (unsigned int )dta.size;
  702. #endif
  703.                   strcpy( final_name, dta.name );
  704.                   CLEAR_IOERR();
  705.                   return final_name;             /* signal what file we got */
  706.                end
  707.  
  708.          end
  709.       CLEAR_IOERR();
  710.       return NULL;
  711.  
  712.    end
  713.  
  714. /* END OF FILE: recv_sl.c */
  715.  
  716.